#include "types/common.h"
#include "types/record_info.h"
#include "types/record.h"
#include "types/bptree.h"

#ifndef _record_mgr_h_
#define _record_mgr_h_

//How RecordManager will be used:

//The following operations:
//Create Table:
//	Record manager will inturn call buffer manager to create info
//	Record manager wil have its own repository on the table, number of blocks and empty slot information. An entry will be added there.
//Commit:
//	Record manager will pass this on to the buffer manager
//Insert:
//	add_record function needs to be called
// 		For each record there is a record structure defined in record.h
//		It can be instantiated as an empty record, record with values and record with id and values
//		The executor has to instantiate it with values passing number of attributes and a vector containing the values
// 		This has to be passed as argument to the add_record function
//Select:
//	read_record function needs to be called
//		The read record function will return a vector of record objects
//		If the select statement is for a specific attribute the executor has to filter while displaying
//		There is an id field in Record class. This need not be populated for insertion.
//		The record object generated by read record will have id populated containing the block number and slot number from which it was retrieved.

//	read record can be called with one condition
//		The condition is defined as the struct Condition in record.h
//		The condition object will have the following information:
//		left hand side and right had side of the condition (the operands)
//		The operation to be done : whether it is == (eq), != (ne), <=(le), >=(ge), <(lt), >(gt)
//		The condition has two types:
//			value check : Suppose we have to check if the 3rd attribute is 20, lvalue will be 3 and rvalue will be 20 and type is val_check
//			attr check	: Suppose we have to check if the 3rd attribute is equal to 5th attribute, lvalue will be 3, rvalue will be 5 and type is attr_check

//	There are two function merge_records and common_records that will do an union or intersection of two vector of records.
//		This is for use during implementation of AND and OR.
//		This union and intersection operation will be based on the record id. Hence the executor should always pass the vector got from read_records or 
//		merge_records or common _records.

//	Print
//	For commands like print hit rate and print buffer record manager's print will be called as print("HIT RATE") or print("BUFFER")
//	This will be passed on to buffer manager
class RecordManager
{
public:
	inline RecordManager () : ri(*RecordInfo::inst()), bm(BufferManager::inst())
	{
	}
	
	RecordId add_record(string &tblname, Record rec, bool updatecache = true);
	vector<Record> read_records(string &tblname);
	
	//  vector<Record> read_records(string &tblname, Condition cond); //Obselete
	

	inline void create_table(string &tblname, UINT32 num_attrs) 
	{
		ri.set_table_info(tblname, BLOCK_SIZE/(4*num_attrs));
		bm.create_table(tblname);
	}
	inline void commit()
	{
		bm.commit();
	}
	
	vector<Record> merge_records(vector<Record> set1, vector<Record> set2);
	vector<Record> common_records(vector<Record> set1, vector<Record> set2);

	//INDEX CHANGES	
	//Functions for supporting indexing
	//create_index would create an index file with one block header.
	//The header would store the information whether it is an index supporting duplicate or not
	//This will create an empty B+ Tree and insert the records if present.
	//The internal index file name would be a combination of IndexName and Table name
	//The catalog - executor will take care of not supporting creating index twice on the same attribute.
	void create_index(string &tblname, UINT32 attr_index, string &index_name, bool dupAllowed);	
	
	//During each insert the record manager will also get a vector of index names
	//The vector would contain null string ("") if the attribute is not indexed
	//If the record is indexed then insertion also update B+ tree
	//TBD: Will the vector slow down every insert operation?
	RecordId add_record(string &tblname, Record rec, vector<string> index_name);	
	
	//This would use B+ tree index to locate an index.
	vector<Record> read_records(string &tblname, Condition cond, string index_name = "");	
	
	//Other support functions
	
	//If the argument is "INDEX <indexname> of TABLE
	inline void print(string what)
	{
		bm.print(what);
	}

	inline void print(string table_name, string index_name){
		bptree index(internal_index_name(index_name, table_name));
		index.print(index_name);
	}
	
	//Set index debug 
	void set_index_debug(bool state);
	
	inline string internal_index_name(string index_name, string table_name)
	{
		return table_name + "_" + index_name;
	}
	
private:
	RecordInfo &ri;
	BufferManager &bm;
	vector<Record> search_indexed_attr(string tblname, string index_name, Condition cond, bptree &index);
	Record fetch_record(string &tablename,RecordId id);
};

#endif
